package coreBiz

import (
	"bytes"
	"compress/zlib"
	"encoding/base64"
	"fmt"
	"io"
	"strings"
)

// IdCardEncode 身份证号加密
func IdCardEncode(idcard string) (string, error) {
	// 输入验证
	if len(idcard) == 0 {
		return "", fmt.Errorf("身份证号不能为空")
	}
	if len(idcard) != 18 {
		return "", fmt.Errorf("身份证号长度必须为18位")
	}

	// 计算MD5并获取后3位
	md5Str := strings.ToUpper(Md5(idcard))
	str1 := md5Str[len(md5Str)-3:]

	// 压缩身份证号+MD5后3位
	var buf bytes.Buffer
	zw := zlib.NewWriter(&buf)
	_, err := zw.Write([]byte(idcard + str1))
	if err != nil {
		return "", fmt.Errorf("zlib压缩失败: %w", err)
	}
	err = zw.Close()
	if err != nil {
		return "", fmt.Errorf("zlib关闭失败: %w", err)
	}

	// Base64编码
	str3 := base64.StdEncoding.EncodeToString(buf.Bytes())

	// 计算Base64编码后的等号数量
	str2 := strings.Count(str3, "=")

	// 组合结果
	res := str1 + fmt.Sprintf("%d", str2) + str3

	// 去掉等号
	if str2 > 0 {
		res = strings.ReplaceAll(res, "=", "")
	}

	// 替换特殊字符
	res = strings.NewReplacer("+", "-", "/", "_").Replace(res)

	return res, nil
}

// IdCardDecode 身份证号解密
func IdCardDecode(encodedStr string) (string, error) {
	// 输入验证
	if len(encodedStr) == 0 {
		return "", fmt.Errorf("加密字符串不能为空")
	}
	if len(encodedStr) < 4 {
		return "", fmt.Errorf("加密字符串格式不正确")
	}

	// 替换特殊字符
	encodedStr = strings.NewReplacer("-", "+", "_", "/").Replace(encodedStr)

	// 获取Base64编码后的等号数量
	str2 := encodedStr[3:4]
	equalsCount := 0
	_, err := fmt.Sscanf(str2, "%d", &equalsCount)
	if err != nil {
		return "", fmt.Errorf("解析等号数量失败: %w", err)
	}

	// 添加等号
	base64Str := encodedStr[4:]
	for i := 0; i < equalsCount; i++ {
		base64Str += "="
	}

	// Base64解码
	zlibData, err := base64.StdEncoding.DecodeString(base64Str)
	if err != nil {
		return "", fmt.Errorf("Base64解码失败: %w", err)
	}

	// Zlib解压缩
	zr, err := zlib.NewReader(bytes.NewReader(zlibData))
	if err != nil {
		return "", fmt.Errorf("创建zlib解压缩器失败: %w", err)
	}
	defer zr.Close()

	// 读取解压缩后的数据
	decompressed, err := io.ReadAll(zr)
	if err != nil {
		return "", fmt.Errorf("zlib解压缩失败: %w", err)
	}

	// 去掉最后3位MD5校验码
	idcard := string(decompressed[:len(decompressed)-3])

	return idcard, nil
}
